feat(ledmatrix-music): opt-in adaptive layout + core element-style resolver (v1.1.1)#187
feat(ledmatrix-music): opt-in adaptive layout + core element-style resolver (v1.1.1)#187ChuckBuilds wants to merge 3 commits into
Conversation
Add layout_mode: "classic" | "adaptive" (default classic — rendering is byte-identical unless the user opts in; verified by a golden-comparison test across the full harness size spread). Adaptive mode scales the title/artist/album fonts to the panel height, matching how the album art already scales (album_art_size = matrix_height has always been fully height-driven — only the text sizes were fixed). MusicPlugin is itself a BasePlugin, so it gets self.layout for free — unlike football-scoreboard's GameRenderer (a standalone helper class), no separate LayoutContext/FontManager wiring was needed. The vertical space above the progress bar splits into three equal rows via Region; each row's font is the largest crisp ladder rung whose LINE HEIGHT fits that row — height-only, not width, since long titles/artists/albums scroll rather than shrink (the existing marquee scroll/pause state machine is completely untouched; only the font objects and Y positions feeding into it change). Ladder reuses the same rungs verified crisp in text-display/ football-scoreboard (measure_font_crispness == 0.0): PressStart2P at exact multiples of its 8px design grid, plus 4x6-font at its actual crisp size (7px, not 6). User-configured fonts/sizes for title_text/ artist_text/album_text win over auto-sizing; y_percent overrides still apply on top of the computed row position. Revert path: set layout_mode back to "classic" in config (no reinstall), or git-revert this single commit. Tests: test_adaptive_layout_mode.py — classic-unchanged byte-identity across 5 sizes, title font height grows with panel height (measured from actual rendered pixels, not re-derived math), user-font-wins, ladder crispness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_user_font_set() treated the mere PRESENCE of customization.<element>.font or .font_size as 'the user explicitly forced this font' and skipped adaptive sizing. But the web UI's save flow (schema_manager.merge_with_defaults, api_v3.py save_plugin_config) writes the FULL schema-declared default object into config.json on every save -- for every plugin, whether or not the user touched that section. Since config_schema.json declares a font/font_size default for every element (title_text, artist_text, album_text), ANY config that has ever been saved once via the web UI already has these keys present -- meaning _user_font_set() returned True unconditionally, and adaptive font sizing never actually engaged in practice, only in a from-scratch config that had never touched the settings page. Fixed by comparing the configured (font, font_size) against the classic default for that element, not just checking presence -- only a genuine deviation from the default counts as a user override now. Verified: a config carrying only schema defaults now correctly enables adaptive sizing; a real override (e.g. 12px instead of 8px) is still respected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Delegate font loading and the user-font-override check to src.element_style (new core module) instead of the plugin-local copies. The resolver reads its override reference from this plugin's own config_schema.json, so it works in every context — including the test harness and dev server, where BasePlugin.style_resolver would degrade because the mock plugin manager has no schema manager (which is also why the resolver is cached on its own attribute, not BasePlugin's). Behavior-identical: verified byte-identical renders old-vs-new across 6 configs (bare/realistic/partial x classic/adaptive + a real override) and 5 panel sizes (30 comparisons). The empty-customization early-out (display_manager fonts) and y_percent positioning are untouched; the local loader remains as the fallback path on older cores. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam
|
Warning Review limit reached
Next review available in: 59 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| ErrorProne | 1 high |
🟢 Metrics 38 complexity
Metric Results Complexity 38
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Summary
Verification
🤖 Generated with Claude Code
https://claude.ai/code/session_01FqzC1nzTWL4kaqgMaQZFam